#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <fcntl.h>

#include "token.h"


typedef unsigned int uint;
typedef unsigned char uchar;

#define	BSIZE	18192

#define	YYCTYPE		uchar
#define	YYCURSOR	cursor
#define	YYLIMIT		s->lim
#define	YYMARKER	s->ptr
#define	YYFILL(n)	{cursor = fill(s, cursor);}

#define	RET(i)	{s->cur = cursor; return i;}

typedef struct Scanner {
    int			fd;
    uchar		*bot, *tok, *ptr, *cur, *pos, *lim, *top, *eof;
    uint		line;
} Scanner;

uchar *fill(Scanner *s, uchar *cursor){
	if(!s->eof) {
		uint cnt = s->tok - s->bot;
		if(cnt){
			memcpy(s->bot, s->tok, s->lim - s->tok);
			s->tok = s->bot;
			s->ptr -= cnt;
			cursor -= cnt;
			s->pos -= cnt;
			s->lim -= cnt;
		}
		if((s->top - s->lim) < BSIZE){
			uchar *buf = (uchar*) malloc(((s->lim - s->bot) + BSIZE)*sizeof(uchar));
			memcpy(buf, s->tok, s->lim - s->tok);
			s->tok = buf;
			s->ptr = &buf[s->ptr - s->bot];
			cursor = &buf[cursor - s->bot];
			s->pos = &buf[s->pos - s->bot];
			s->lim = &buf[s->lim - s->bot];
			s->top = &s->lim[BSIZE];
			free(s->bot);
			s->bot = buf;
		}
		if((cnt = read(s->fd, (char*) s->lim, BSIZE)) != BSIZE){
			s->eof = &s->lim[cnt]; *(s->eof)++ = '\n';
		}
		s->lim += cnt;
	}
	return cursor;
}

int scan(Scanner *s){
	uchar *cursor = s->cur;
	
std:
	s->tok = cursor;

/*!re2c
any	= [\000-\377];
O	= [0-7];
D	= [0-9];
L	= [a-zA-Z_];
H	= [a-fA-F0-9];
E	= [Ee] [+-]? D+;
FS	= [fFlL];
IS	= [uUlL]*;
ESC	= [\\] ([abfnrtv?'"\\] | "x" H+ | O+);
*/

/*!re2c
	"{{"		{ goto JS; }
	"//"		{ goto line_comment; }
	"/*"		{ goto comment; }

	"\n"
	    {
			if(cursor == s->eof) RET(EOI);
			s->pos = cursor; s->line++;
			goto std;
	    }

	any			{ goto std; }
*/

//	"}}"			{ goto std; }
	
ccc:	
/*!re2c
	"\n"
	    {
			if(cursor == s->eof) RET(EOI);
			s->pos = cursor; s->line++;
			goto std;
	    }
*/
	
	
JS:
/*!re2c
	
	"var"			{ RET(VAR); }
	"function"		{ RET(FUNCTION); }
	"throw"			{ RET(THROW); }
	"catch"			{ RET(CATCH); }
	"new"			{ RET(NEW); }
	"delete"		{ RET(DELETE); }
	"break"			{ RET(BREAK); }
	"case"			{ RET(CASE); }
	"continue"		{ RET(CONTINUE); }
	"default"		{ RET(DEFAULT); }
	"else"			{ RET(ELSE); }
	"for"			{ RET(FOR); }
	"if"			{ RET(IF); }
	"return"		{ RET(RETURN); }
	"typeof"		{ RET(TYPEOF); }
	"switch"		{ RET(SWITCH); }
	"void"			{ RET(VOID); }
	"while"			{ RET(WHILE); }
	"in"			{ RET(IN); }
	
	
	L (L|D)*		{ RET(ID); }
/*	"#" L (L|D)*	{ RET(JSID); }
*/	
	("0" [xX] H+ IS?) | ("0" D+ IS?) | (D+ IS?) |
	(['] (ESC|any\[\n\\'])* ['])
				{ RET(NUMBER); }
	
	(["] (ESC|any\[\n\\"])* ["])
				{ RET(STRING); }
	
	"=="		{ RET(DEQ); }
	"!="		{ RET(NEQ); }
	";"			{ RET(';'); }
	"{"			{ RET('{'); }
	"}"			{ RET('}'); }
	","			{ RET(','); }
	":"			{ RET(':'); }
	"="			{ RET('='); }
	"("			{ RET('('); }
	")"			{ RET(')'); }
	"["			{ RET('['); }
	"]"			{ RET(']'); }
	"."			{ RET('.'); }
	"&"			{ RET('&'); }
	"!"			{ RET('!'); }
	"~"			{ RET('~'); }
	"-"			{ RET('-'); }
	"+"			{ RET('+'); }
	"*"			{ RET('*'); }
	"/"			{ RET('/'); }
	"%"			{ RET('%'); }
	"<"			{ RET('<'); }
	">"			{ RET('>'); }
	"^"			{ RET('^'); }
	"|"			{ RET('|'); }
	"?"			{ RET('?'); }
	
	"\n"
	    {
			if(cursor == s->eof) RET(EOI);
			s->pos = cursor; s->line++;
			//goto JS;
	    }
	any			{ goto JS; }
*/


comment:
/*!re2c
	"*/"			{ RET(COMMENT); goto std; }
	"\n"
	    {
		if(cursor == s->eof) RET(EOI);
		s->tok = s->pos = cursor; s->line++;
		goto comment;
	    }
        any			{ goto comment; }
*/


line_comment:
/*!re2c
	"\n"			{ RET(COMMENT); goto std; }
        any			{ goto line_comment; }
*/



}

do_scan(){
    Scanner in;
    int t;
    memset((char*) &in, 0, sizeof(in));
    
//    int fd = open("test.cj", O_RDONLY);
    
    in.fd = 0;
    while((t = scan(&in)) != EOI){
    	if(t==ANY) {
    		printf("*ERROR*");
    		break;
    	}
    		

	printf("%d ", t);
	print_token(t);

	printf("%d\t%.*s\n", t, in.cur - in.tok, in.tok);
	printf("%d\n", t);

    }
    close(in.fd);
}
